Skip to content

Resolve same-named schemas from different files as distinct components (fixes #2333) - #2349

Merged
ewaostrowska merged 4 commits into
swagger-api:masterfrom
seonwooj0810:fix/issue-2333-same-name-external-ref-collision
Aug 17, 2026
Merged

ewaostrowska merged 4 commits into
swagger-api:masterfrom
seonwooj0810:fix/issue-2333-same-name-external-ref-collision

Conversation

@seonwooj0810

Copy link
Copy Markdown
Contributor

Fixes #2333

Problem

When parsing a spec with resolve: true where two schemas in different files share the same name, both references collapse into the first model. In the issue's reproducer, SomeItem (→ inventory.yaml#/components/schemas/Pet, has name) and Pet (→ pets.yaml#/components/schemas/Pet, has id) both end up pointing at inventory's Pet.

Root cause

ExternalRefProcessor.finalNameRec decides which name a freshly resolved external schema gets. When the candidate name is already taken by an entry that still carries a $ref (an unresolved external placeholder, e.g. the sibling Pet component pointing at pets.yaml), the code unconditionally treated that slot as free and reused the name — then addSchemas(newRef, schema) overwrote the placeholder. The distinct second schema was lost.

Fix

A $ref placeholder slot is only safe to reuse when it targets the same reference currently being resolved. The incoming $ref is now threaded into finalNameRec; if the existing placeholder points to a different target, resolution falls through to the next suffixed name (Pet_1) instead of clobbering it. This is the conservative direction — a mismatch only ever produces an extra suffixed name, never data loss.

Result on the reproducer

SomeItem -> { name }     (inventory.yaml Pet)
Pet      -> { id }       (pets.yaml Pet)
Pet_1    -> { name }

SomeItem correctly carries name and Pet correctly carries id.

Test evidence

  • Added Issue2333Test with the issue's three-file reproducer asserting the two Pet schemas resolve distinctly. Passes.
  • Full swagger-parser-v3 module suite: 609 tests, 0 failures, 0 errors (run with -Dmaven.javadoc.skip=true; the offline javadoc fetch and the unrelated swagger-parser-safe-url-resolver PermittedUrlsCheckerTest failures are pre-existing JDK 25 environment issues, not related to this change).

Verification done

  1. No in-flight PR (gh pr list search for the issue/keywords — none open); 2. no self-claim in the thread; 3. code-focused (.java); 4. reproduced the bug on master, confirmed the fix flips the behavior; 5. confirmed root symbol finalNameRec/processRefToExternalSchema still present on master; 6. n/a (no parent epic).

@seonwooj0810

Copy link
Copy Markdown
Contributor Author

Gentle ping — open since mid-June.

Recap of #2333: with resolve: true, two schemas with the same name in different files collapse into the first model, because ExternalRefProcessor.finalNameRec treats an existing entry that still carries a $ref (an unresolved external placeholder) as a match and reuses its name. The PR keeps them distinct.

Is there anything you'd like adjusted before this can be considered — naming strategy for the second component in particular? Still merges cleanly and both checks are green.

When resolving with resolveFully/resolve, an external $ref whose target
shares a name with another, not-yet-resolved external $ref placeholder
caused the placeholder to be silently overwritten. ExternalRefProcessor's
finalNameRec treated any existing schema that still carried a $ref as a
free slot, so two distinct files defining e.g. 'Pet' collapsed into one.

Only reuse the existing name when the placeholder $ref targets the same
reference being resolved; otherwise fall through to a suffixed name.

Fixes swagger-api#2333
@ewaostrowska
ewaostrowska force-pushed the fix/issue-2333-same-name-external-ref-collision branch from 0edeeb6 to b67060a Compare August 17, 2026 08:33
@ewaostrowska

Copy link
Copy Markdown
Contributor

Hi @seonwooj0810! Thank you for the PR :)

Since this PR was opened, #2105 introduced canonical $ref identity in ResolverCache. I've rebased the local changes on that, so the fix uses the same normalization instead of raw string equality. That keeps distinct refs separate and deduplicates equivalent paths containing . or ...

The regression tests cover both behaviors to stay compatible with #2105.

@ewaostrowska

Copy link
Copy Markdown
Contributor

One note here: This PR fixes the collision for components/schemas only. The same problem exists in components/responses and components/parameters too, most likely others as well, but fixing all component types needs a shared naming mechanism and more tests. Better to keep this PR focused on the reported case and open a separate issue for the rest.

@ewaostrowska
ewaostrowska merged commit eef1cd2 into swagger-api:master Aug 17, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Parser confuses referenced models with same name

4 participants